#![allow(non_upper_case_globals, non_snake_case)]

use cgmath::{perspective, vec3, Deg, Matrix4, Point3};
use gl_rs::utils::camera::Camera;
use gl_rs::utils::common::{process_events, process_input};
use gl_rs::utils::model::Model;
use gl_rs::utils::shader::Shader;
use glfw;
use glfw::Context;

const SCR_WIDTH: u32 = 960;
const SCR_HEIGHT: u32 = 544;

pub fn main_3_1_1() {
    let mut camera = Camera {
        position: Point3::new(0.0, 0.0, 3.0),
        ..Camera::default()
    };

    let mut first_mouse = true;
    let mut last_x: f32 = SCR_WIDTH as f32 / 2.0;
    let mut last_y: f32 = SCR_HEIGHT as f32 / 2.0;

    let mut delta_time: f32;
    let mut last_frame: f32 = 0.0;

    let mut fw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    fw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    fw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    #[cfg(target_os = "macos")]
    fw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    let (mut window, events) = fw
        .create_window(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window");
    window.make_current();
    window.set_framebuffer_size_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_scroll_polling(true);
    window.set_cursor_mode(glfw::CursorMode::Disabled);

    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    let (our_shader, our_mode) = unsafe {
        gl::Enable(gl::DEPTH_TEST);
        let our_shader = Shader::new(
            "src/_3_model_loading/shaders/1.model_loading.vert",
            "src/_3_model_loading/shaders/1.model_loading.frag",
        );
        let our_model = Model::new("resources/objects/nanosuit/nanosuit.obj");

        (our_shader, our_model)
    };

    while !window.should_close() {
        let current_frame = fw.get_time() as f32;
        delta_time = current_frame - last_frame;
        last_frame = current_frame;

        process_events(&events, &mut first_mouse, &mut last_x, &mut last_y, &mut camera);
        process_input(&mut window, delta_time, &mut camera);

        unsafe {
            gl::ClearColor(0.1, 0.1, 0.1, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
            our_shader.use_program();
            let projection = perspective(Deg(camera.zoom), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 100.0);
            let view = camera.get_view_matrix();
            our_shader.set_mat4(c_str!("projection"), &projection);
            our_shader.set_mat4(c_str!("view"), &view);
            let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -1.75, 0.0));
            model = model * Matrix4::from_scale(0.2);
            our_shader.set_mat4(c_str!("model"), &model);
            our_mode.draw(&our_shader);
        }
        window.swap_buffers();
        fw.poll_events();
    }
}
